Skip to content

Add OTEL_SEMCONV_EXCEPTION_SIGNAL_OPT_IN support to record_exception#5323

Open
RKest wants to merge 1 commit into
open-telemetry:mainfrom
RKest:record-exception-signal-opt-in
Open

Add OTEL_SEMCONV_EXCEPTION_SIGNAL_OPT_IN support to record_exception#5323
RKest wants to merge 1 commit into
open-telemetry:mainfrom
RKest:record-exception-signal-opt-in

Conversation

@RKest

@RKest RKest commented Jun 18, 2026

Copy link
Copy Markdown

Description

Span.record_exception currently always records exceptions as span
events
. The semantic conventions for
exceptions in logs
and the span-event API deprecation plan
(OTEP 4430,
see also the
Deprecating Span Events
blog post) introduce the OTEL_SEMCONV_EXCEPTION_SIGNAL_OPT_IN environment
variable so instrumentations can migrate exceptions from span events to logs.

This PR makes the SDK's Span.record_exception (and therefore the
__exit__ / use_span paths that call it) honor
OTEL_SEMCONV_EXCEPTION_SIGNAL_OPT_IN:

Value Behavior
(unset) Span events only — existing behavior (default).
logs Record the exception as a log only.
logs/dup Record the exception as both a log and a span event (phased rollout).

Any unrecognized value is treated as unset, preserving today's behavior.

Implementation notes:

  • The exception log is emitted via the global LoggerProvider, correlated
    with the originating span's context (trace_id / span_id), at ERROR
    severity, with event_name="exception".
  • The log carries exception.type, exception.message and
    exception.stacktrace. The deprecated exception.escaped attribute is
    intentionally omitted from the log representation; it is still set on the
    span event when one is recorded (logs/dup or default).
  • The log is emitted under the span's own instrumentation scope.
  • OTEL_SEMCONV_EXCEPTION_SIGNAL_OPT_IN is an experimental, transitional
    opt-in, so it is kept private to opentelemetry.sdk.trace rather than
    exported from opentelemetry.sdk.environment_variables.

The default behavior is unchanged, so this is fully backwards compatible and
opt-in.

Type of change

  • New feature (non-breaking change which adds functionality)

How Has This Been Tested?

A new test module opentelemetry-sdk/tests/trace/test_record_exception_logs.py
covers all modes end to end using an in-memory span exporter and a captured
logger:

  • unset / unrecognized values record a span event and emit no log
  • logs records a log only (no span event)
  • logs/dup records both a log and a span event
  • the emitted log is correlated with the originating span
    (trace_id / span_id)
  • the log uses the span's instrumentation scope
  • exception.type / exception.message / exception.stacktrace are
    populated and extra attributes are forwarded
  • the deprecated exception.escaped attribute is not set on the log

The existing record_exception tests in
opentelemetry-sdk/tests/trace/test_trace.py continue to pass unchanged.

uv run pytest opentelemetry-sdk/tests/trace/test_record_exception_logs.py
uv run pytest opentelemetry-sdk/tests/trace/test_trace.py -k record_exception

Does This PR Require a Contrib Repo Change?

  • Yes. - Link to PR:
  • No. The record_exception signature is unchanged; the new behavior is
    gated behind an environment variable and defaults to today's behavior.

Checklist:

  • Followed the style guidelines of this project (ruff check / ruff format)
  • Changelogs have been updated (.changelog/5318.added — rename to match
    the assigned PR number when opening the PR)
  • Unit tests have been added
  • Documentation has been updated (env var docstring + record_exception
    docstring)

@RKest RKest requested a review from a team as a code owner June 18, 2026 12:38
@aabmass aabmass requested a review from Copilot June 24, 2026 20:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds opt-in support for recording exceptions as logs (and optionally duplicating to span events) in the SDK’s Span.record_exception, enabling migration away from span events per the exception-as-logs semantic conventions and the span-event deprecation plan.

Changes:

  • Update Span.record_exception to honor OTEL_SEMCONV_EXCEPTION_SIGNAL_OPT_IN and emit an exception LogRecord correlated with the span when configured.
  • Add end-to-end unit tests covering unset/unrecognized/logs/logs-dup behaviors, correlation, scope usage, and attribute mapping.
  • Add a changelog entry documenting the new opt-in behavior.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
opentelemetry-sdk/src/opentelemetry/sdk/trace/init.py Adds env-var gated branching in record_exception and a helper to emit correlated exception logs.
opentelemetry-sdk/tests/trace/test_record_exception_logs.py New tests validating exception-as-logs behavior across all opt-in modes.
.changelog/5318.added Notes the new env-var controlled behavior for Span.record_exception.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py
Comment thread opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py Outdated
`Span.record_exception` now honors the `OTEL_SEMCONV_EXCEPTION_SIGNAL_OPT_IN`
environment variable, per the semantic conventions for exceptions in logs
(https://opentelemetry.io/docs/specs/semconv/exceptions/exceptions-logs/):

- unset: record exceptions as span events only (unchanged default)
- `logs`: record exceptions as logs only
- `logs/dup`: record exceptions as both logs and span events

Exception logs are emitted at ERROR severity, correlated with the
originating span's context, and use the span's instrumentation scope.
@RKest RKest force-pushed the record-exception-signal-opt-in branch from 828822d to e039edd Compare June 29, 2026 18:03
@RKest RKest requested a review from Copilot June 29, 2026 18:04

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

# representation.
exception_logger.emit(
LogRecord(
timestamp=timestamp,
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants